<?php
/**
 * 用户的相关验证方法
 *
 * @author xiaoxia.xu <xiaoxia.xuxx@aliyun-inc.com>
 * @copyright ©2003-2103 phpwind.com
 * @license http://www.phpwind.com
 * @version $Id: PwUserValidator.php 20770 2012-11-07 07:55:24Z xiaoxia.xuxx $
 * @package  src.service.user.validator
 */
class UserValidator {

    /**
     * 检测用户名的合法性
     */
    static public function isUsername($username) {
        //匹配用户名只能含有中文、数字、大小写字母、'.'、_
        return preg_match('/^[\x7f-\xff\dA-Za-z\.\_]+$/', $username);
    }

    /**
     * 检查用户的手机号码是否合法
     */
    static public function isMobile($mobile) {
        return preg_match('/^1[3|5]\d{8}$/', $mobile);
    }

    /**
     * 检测固定电话号码是否正确
     */
    static public function isTelPhone($telPhone) {
        return preg_match('/^[0-9][-\d]*\d*$/', $telPhone);
    }

    /**
     * 检查用户的邮箱
     */
    static public function isEmail($email) {
        return strlen($email) > 6 && preg_match("/^[\w\-\.]+@[\w\-\.]+(\.\w+)+$/", $email);;
    }

    /**
     * 检查用户名的唯一性
     */
    static public function checkUsernameExist($username, $uid = 0) {
        return self::checkExists('username', $username, $uid);
    }

    /**
     * 检查用户邮箱的唯一性
     */
    static public function checkEmailExist($email, $uid = 0) {
        return self::checkExists('email', $email, $uid);
    }

    /**
     * 检查用户手机号码的唯一性
     */
    static public function checkMobileExist($mobile, $uid = 0) {
        return self::checkExists('mobile', $mobile, $uid);
    }

    /**
     * 检查用户某字段（mobile/email/username)的唯一性
     *
     * @param string 字段
     * @param string 字段值
     * @param int    需要排除的 uid
     * @return bool  是否存在
     */
    static protected function checkExist($field, $value, $exUid = 0) {
        $sql = sprintf("SELECT uid FROM `".Db::table('user')."` WHERE `{$field}` = '%s'", Db::escape($value));
        $uid = Db::getFirst($sql);

        if(!$uid) return false;
        return ($uid != intval($exUid));
    }

    /**
     * 检查用户的email是否存在
     *
     * @param string $username  待检查的用户名
     * @param int $exceptUid 排除的用户ID
     * @return boolean
     */
    static public function checkUsernameExist($username, $exceptUid = 0) {
        /* @var $userDs PwUser */
        $userDs = Wekit::load('user.PwUser');
        $info = $userDs->getUserByName($username, PwUser::FETCH_MAIN);
        if (!$info) return false;
        $exceptUid = intval($exceptUid);
        if ($exceptUid && $info['uid'] == $exceptUid) return false;
        return true;
    }

    /**
     * 检查用户的密码是否合法
     *
     * @param string $password 用户密码
     * @param string $username 用户名
     * @return PwError|boolean

    static public function isPwdValid($password, $username) {
        $config = Wekit::C('register');
        $len = strlen($password);
        if ($config['security.password.min'] > $len || $config['security.password.max'] < $len) {
            return new PwError('USER:user.error.-11', array('{min}' => $config['security.password.min'], '{max}' => $config['security.password.max']));
        }
        $result = self::checkPwdComplex($password, $username);
        if ($result instanceof PwError) return $result;
        return true;
    }*/

    /**
     * 验证密码的复杂度是否符合后台设置要求
     * 检查密码复杂度
     * 检查用户名和密码是否允许相同
     * 如果设置不允许相同而相同则返回PwError
     * 其余返回true
     *
     * @param string $password 用户密码
     * @param string $username 用户名
     * @return boolean|PwError

    static public function checkPwdComplex($password, $username) {
        $register = Wekit::C('register');
        if (!($pwdConfig = $register['security.password'])) return true;
        $config = array_sum($pwdConfig);
        if (in_array(9, $pwdConfig)) {
            $config = $config - 9;
            if ($username == $password) return new PwError('USER:pwd.error.equalUsername');
        }
        if ($config == 0) return true;
        if (self::_complexCaculate($password, $config)) return new PwError('USER:pwd.error.complex', array('{type}' => self::buildPwdComplexMsg($pwdConfig)));
        return true;
    } */

    /**
     * 构造用户密码复杂度的校验规则
     *
     * @param array  复杂规则的配置
     * @return string
     */
    private static function buildPwdComplexMsg($config) {
        if (!$config) return '';
        $complex = array(1 => '小写字母', 2 => '大写字母', 4 => '数字', 8 => '非空白符号', 9 => '不能和用户名相同');
        return implode('、', array_intersect_key($complex, array_flip($config)));
    }

    /**
     * 复杂度判断
     *
     * @param string 密码
     * @param int    配置
     * @return boolean
     */
    private static function _complexCaculate($password, $config) {
        $pwdLen = strlen($password);
        $complex = 0;
        for ($i = 0; $i < $pwdLen; $i ++) {
            $ascii = ord($password[$i]);
            //必须含有小写字母 97-122
            if (1 == ($config & 1) && $ascii >= 97 && $ascii <= 122) {
                if (0 == $complex || 1 != ($complex & 1)) $complex += 1;
                continue;
            }
            //必须含有大写字母 65-90
            if (2 == ($config & 2) && $ascii >= 65 && $ascii <= 90) {
                if (0 == $complex || 2 != ($complex & 2)) $complex += 2;
                continue;
            }
            //必须含有数字 48-57
            if (4 == ($config & 4) && $ascii >= 48 && $ascii <= 57) {
                if (0 == $complex || 4 != ($complex & 4)) $complex += 4;
                continue;
            }
            //必须含有符号 33-47/58-64/91-96/123-126
            if (8 == ($config & 8) &&
                (($ascii >= 33 && $ascii <=47) || ($ascii >= 58 && $ascii <= 64) || ($ascii >= 91 && $ascii <= 96) || ($ascii >= 123 && $ascii <= 126))) {
                    if (0 == $complex || 8 != ($complex & 8)) $complex += 8;
                    continue;
            }
            //已经达到设置复杂度则跳出
            if ($config == $complex) break;
        }
        return $config != $complex;
    }
}
?>